<?php

namespace App\Model;

use App\Services\AdapayService;
use App\Services\BankService;
use App\Services\Iot\IotService1 as IotService;
use Hyperf\Database\Model\Relations\BelongsTo;
use Hyperf\Utils\Arr;
use Hyperf\Redis\Redis;
use Carbon\Carbon;
use Util\Common;

/**
 * App\Order
 *
 * @property int $id
 * @property int $device_id 设备编号
 * @property string $number 订单号
 * @property string $sn 设备编号
 * @property string $payment_type 订单类型
 * @property int $channel_number 通道号
 * @property int $station_id 站点id
 * @property int $user_id 用户
 * @property \Carbon\Carbon|null $estimate_stop_at 预选停止时间
 * @property int|null $duration_seconds 使用时长 秒
 * @property int|null $platform_profit 平台收益
 * @property \Carbon\Carbon|null $stop_at 停止时间
 * @property string|null $stop_reason 停止原因
 * @property string $status 状态
 * @property-read \App\Model\Device $device
 * @property-read \App\Model\Feedback $feedback
 * @property-read \App\Model\Station $station
 * @property-read \App\Model\User $user
 * @property-read \App\Model\CouponRecord $couponRecord
 */
class Order extends Model
{

    public bool $timestamps = true;
    protected ?string $table = 'orders';


    public static array $paymentTypeMap = [
        Bill::PAYMENT_TYPE_WE_CHAT_PAY => '微信支付',
        Bill::PAYMENT_TYPE_ALI_PAY => '支付宝支付',
        Bill::PAYMENT_TYPE_BALANCE => '余额',
        Bill::PAYMENT_TYPE_IC_CARD => '刷卡',
    ];

    protected array $casts = [
        'estimate_stop_at' => 'datetime',
        'stop_at' => 'datetime',
        'extra' => 'json',
    ];
    protected array $fillable = [
        'device_id','number','sn','user_id','payment_type',
        'channel_number','station_id','fee','minutes',
        'estimate_stop_at','estimate_minutes','platform_profit',
        'stop_at','return_fee','is_return_fee','duration_seconds',
        'stop_reason','status','extra','electric_quantity','power',
        'coupon_record_id','original_fee','surplus_electricity',
        'is_fail','power_fee',
        'is_autoload','charge_id','charge_detail_id','out_ord_id',
        'pay_at','refund_at','payment_id','is_check','distributor_id'
    ];

    const FREE_SECONDS = 420;

//    //最长充电时长
//    const MAX_HOURS = 8;

    const RETURN = 1;
    const UNRETURN = 0;

    const STATUS_UNPAID = 'unpaid';
    const STATUS_PAID = 'paid';
    const STATUS_USING = 'using';
    const STATUS_END = 'end';
    const STATUS_FAILED = 'failed';
    const STATUS_REFUNDED = 'refunded';
    const STATUS_PAY_TIMEOUT = 'timeout';

    const STATUS_MAP = [
        self::STATUS_UNPAID => '未支付',
        self::STATUS_PAID => '已支付',
        self::STATUS_USING => '使用中',
        self::STATUS_END => '已完成',
        self::STATUS_FAILED => '失败',
        self::STATUS_REFUNDED => '已退款',
        self::STATUS_PAY_TIMEOUT => '支付超时'
    ];

    //关联的账单类型
    const RELATE_BILL_TYPE_MAP = [
        Bill::TYPE_ORDER_PAY,
        Bill::TYPE_DISTRIBUTOR_ORDER_PROFIT,
        Bill::TYPE_DISTRIBUTOR_DIRECT_ORDER_PROFIT,
        Bill::TYPE_PLATFORM_PROFIT,
    ];

    const SUCCESS_REFUND = 1;
    const NORMAL_REFUND = 0;

    public function feedback()
    {
        return $this->hasOne(Feedback::class);
    }

    public function device():BelongsTo
    {
        return $this->belongsTo(Device::class,'device_id','id');
    }

    public function user():BelongsTo
    {
        return $this->belongsTo(User::class,'user_id','id');
    }

    public function couponRecord():BelongsTo
    {
        return $this->belongsTo(CouponRecord::class,'coupon_record_id','id');
    }


    //
    public function getDurationSeconds()
    {
        //使用中的为空
        if($this->status != self::STATUS_USING) {
            return $this->duration_seconds ?? 0;
        }

        return Carbon::now()->timestamp - $this->created_at->timestamp;
    }

    public function getNormalTime(int $power,int $chargeOptionId){
        $chargeDetail = ChargeDetail::where('charge_option_id',$chargeOptionId)
            ->where('type', ChargeDetail::POWER_TYPE)
            ->where('min_power','>=',$power)
            ->where('max_power','<=',$power)
            ->first();
        return $chargeDetail;
    }


    public function getStatusDes()
    {
        return Arr::get(self::STATUS_MAP, $this->status);
    }


    public function getPaymentTypeDes()
    {
        return Arr::get(self::$paymentTypeMap, $this->payment_type);
    }

    //是否需要通知设备停止
    public function stop($reason, $surplusElectric, $notifyDevice = false)
    {
        //这里有默认值的坑 新添加的数据 是数据库赋予的默认值 但是创建后立即对模型进行默认值字段的值判断 会出现问题 模型上改字段为null 但实际数据库中字段为默认值的问题 造成判断错误
        if(!is_null($this->status) && $this->status != self::STATUS_USING) {
             return '';
        }

        $this->duration_seconds = $this->getDurationSeconds();
        $this->status = self::STATUS_END;
        $this->stop_at = Carbon::now();
        $this->stop_reason = $reason;
        $this->surplus_electricity = $surplusElectric;
        $device = $this->device;
        $seconds = $this->minutes*60;
//      if($seconds > $this->duration_seconds && $this->is_autoload == 1) { //根据套餐
        if($seconds > $this->duration_seconds && ($device->is_refund > 0 || $this->is_autoload == 1)){ //根据设备状态
            $this->return_fee  =  number_format( (($seconds-$this->duration_seconds)/$seconds)*$this->original_fee,2);
            if($this->coupon_record_id){
                $use_fee = ($this->duration_seconds/$seconds)*$this->original_fee;
                $decr_fee = $this->original_fee - $this->power_fee;
                if($decr_fee > $use_fee){
                    $this->return_fee = $this->power_fee;
                }
            }
            if($this->return_fee < 0){
               $this->return_fee = 0;
            }
            if($this->return_fee >= $this->power_fee){
                $this->return_fee  = $this->power_fee;
//                $couponRecord = $this->couponRecord;
//                $couponRecord && $couponRecord->markAsUnused();
            }
        }else{
            $this->return_fee = 0;
        }
        try{
            if($this->payment_type == Bill::PAYMENT_TYPE_BALANCE) {
                $this->user->decrementBalance($this->fee - $this->return_fee);
                Bill::record(
                    $this->user,
                    -($this->fee - $this->return_fee),
                    Bill::TYPE_ORDER_PAY,
                    Bill::PAYMENT_TYPE_BALANCE,
                    $this->id
                );
                $this->is_return_fee = self::RETURN;
            }
            if($device->is_refund > 0 || $this->is_autoload == 1){
                if($this->return_fee > 0 ){
                    if($this->payment_type == Bill::PAYMENT_TYPE_BALANCE){
                        $this->distributorSettle();
                    }else{
//                        $refoundParams = array(
//                            "payment_id"=> $this->payment_id,
//                            # 退款订单号
//                            "refund_order_no"=> $this->number,
//                            # 退款金额
//                            "refund_amt"=> $this->return_fee ,
//                            "notify_url" =>Common::MAIN_HOST.'/user/order/refund'
//                        );
//                        $adapayService = new AdapayService();
//                        $adapayService->refundPayment($refoundParams);
                        $normal = new Normal();
                        $data['openid'] = $this->user->openid;
                        $data['number'] = $this->number;
                        $data['order_id'] = $this->out_ord_id;
                        $data['refund_no'] ='RF'.$normal->randOrder($this->device_id);
                        $data['type']  =  1;
                        $data['fee'] = $this->return_fee;
                        $bankService = new BankService();
                        $result = $bankService->refund($data);
                        if($result['return_code'] == 0){
                            $this->is_return_fee = 1;
                            $this->return_fee = $this->return_fee;
                            $this->status = self::STATUS_END;
                        }
                        $this->distributorSettle();
                    }
                }else{
                    $this->distributorSettle();
                }
            }else{
                $this->distributorSettle();
            }
        }catch (\Exception $e){
            Normal::logger($this->id . '结算失败: ' . $e->getMessage(),'order-event');
        }

        //单次刷卡最大用电量 单位为0.1/元 减去剩余电量则为实际电量(传入的电量实际为剩余电量) 所以销售的电量减去剩余电量就是实际使用的电量
        $realElectric = $device->card_elec * 0.1 * $this->original_fee  - $this->surplus_electricity;
        $this->electric_quantity = max($realElectric, 0);
        $this->save();
        if($this->device->port_status){
            $port_status = $this->device->port_status;
            foreach($port_status as $k => &$v){
                if($v['number'] == $this->channel_number){
                    $v['status'] = 1;
                    break;
                }
            }
            $this->device->port_status = $port_status;
            $this->device->save();

        }
        if($notifyDevice) {
            IotService::stop($device->iot_sn, $this->channel_number);
        }
//        if(!$this->is_draw){
//            if($this->distributor_id == 237){
                $this->feeStatics();
//            }
//        }
        //结算
//        $this->settlement();

//        //更新设备参数 以此来计算电量
//        $device->updateParams();

//        //发送消息
//        $user = $this->user;

//        switch ($user->source)
//        {
//            case User::SOURCE_WE_CHAT:
//                //发送消息
//                $message = new Text("您好：充电已停止，请确认！安全充电，人人有责！");
//                $res = WechatService::getApp()->customer_service->message($message)->to($user->openid)->send();
//                logger('send text message', [
//                    'order_id' => $this->id,
//                    'openid' => $user->openid,
//                    'res' => $res,
//                ]);
//
//                break;
//        }

    }

    /**将数据同步给缓存进行统计
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function feeStatics(){
        try{
            $date = date('Y-m-d',time());
            if($this->device->child_distributor_id > 0){
                $countKey = 'DISTRIBUTOR_ORDER_COUNT'.$date.'_'.$this->device->child_distributor_id;
                if($this->is_disabled != 1){
                    $powerKey =  'DISTRIBUTOR_ORDER_POWER_'.$this->device->distributor_id;
                    $returnKey =  'DISTRIBUTOR_ORDER_RETURN_'.$this->device->distributor_id;
                    if(!redis()->exists($powerKey)){
                        $devices = Device::where('distributor_id',$this->device->distributor_id)
                            ->get(['id']);
                        $indDevices = [];
                        foreach($devices as $v){
                            $indDevices[] =$v['id'];
                        }
                        $status = [Order::STATUS_END,Order::STATUS_REFUNDED];
                        $powerFee = Order::whereIn('device_id',$indDevices)
                            ->whereIn('status',$status)
                            ->sum('power_fee');
                        redis()->set($powerKey,$powerFee);
                        $returnFee = Order::whereIn('device_id',$indDevices)
                            ->where('is_return_fee',1)
                            ->sum('return_fee');
                        redis()->set($returnKey,$returnFee);
                    }else{
                        redis()->incrByFloat($powerKey,(float)$this->power_fee);
                        redis()->incrByFloat($returnKey,(float)$this->return_fee);
                    }
                    $powerKey =  'DISTRIBUTOR_ORDER_POWER_'.$date.'_'.$this->device->distributor_id;
                    $returnKey =  'DISTRIBUTOR_ORDER_RETURN_'.$date.'_'.$this->device->distributor_id;
                    if(redis()->exists($powerKey)){
                        redis()->incrByFloat($powerKey,(float)$this->power_fee);
                        redis()->incrByFloat($returnKey,(float)$this->return_fee);
                    }else{
                        redis()->setex($powerKey,60*60*24,$this->power_fee);
                        redis()->setex($returnKey,60*60*24,$this->return_fee);
                    }
                }

                $powerKey =  'DISTRIBUTOR_ORDER_POWER_'.$this->device->child_distributor_id;
                $returnKey =  'DISTRIBUTOR_ORDER_RETURN_'.$this->device->child_distributor_id;
                if(!redis()->exists($powerKey)){
                    $devices = Device::where('child_distributor_id',$this->device->child_distributor_id)
                        ->get(['id']);
                    $indDevices = [];
                    foreach($devices as $v){
                        $indDevices[] =$v['id'];
                    }
                    $status = [Order::STATUS_END,Order::STATUS_REFUNDED];
                    $powerFee = Order::whereIn('device_id',$indDevices)
                        ->whereIn('status',$status)
                        ->sum('power_fee');
                    redis()->set($powerKey,$powerFee);
                    $returnFee = Order::whereIn('device_id',$indDevices)
                        ->where('is_return_fee',1)
                        ->sum('return_fee');
                    redis()->set($returnKey,$returnFee);
                }else{
                    redis()->incrByFloat($powerKey,(float)$this->power_fee);
                    redis()->incrByFloat($returnKey,(float)$this->return_fee);
                }
                $powerKey =  'DISTRIBUTOR_ORDER_POWER_'.$date.'_'.$this->device->child_distributor_id;
                $returnKey =  'DISTRIBUTOR_ORDER_RETURN_'.$date.'_'.$this->device->child_distributor_id;
                if(redis()->exists($powerKey)){
                    redis()->incrByFloat($powerKey,(float)$this->power_fee);
                    redis()->incrByFloat($returnKey,(float)$this->return_fee);
                }else{
                    redis()->setex($powerKey,60*60*24,(float)$this->power_fee);
                    redis()->setex($returnKey,60*60*24,(float)$this->return_fee);
                }

            }else{
                $countKey = 'DISTRIBUTOR_ORDER_COUNT'.$date.'_'.$this->device->distributor_id;
                $powerKey =  'DISTRIBUTOR_ORDER_POWER_'.$this->device->distributor_id;
                $returnKey =  'DISTRIBUTOR_ORDER_RETURN_'.$this->device->distributor_id;
                if(!redis()->exists($powerKey)){
                    $devices = Device::where('distributor_id',$this->device->distributor_id)
                        ->get(['id']);
                    $indDevices = [];
                    foreach($devices as $v){
                        $indDevices[] =$v['id'];
                    }
                    $status = [Order::STATUS_END,Order::STATUS_REFUNDED];
                    $powerFee = Order::whereIn('device_id',$indDevices)
                        ->whereIn('status',$status)
                        ->sum('power_fee');
                    redis()->set($powerKey,$powerFee);
                    $returnFee = Order::whereIn('device_id',$indDevices)
                        ->where('is_return_fee',1)
                        ->sum('return_fee');
                    redis()->set($returnKey,$returnFee);
                }else{
                    redis()->incrByFloat($powerKey,(float)$this->power_fee);
                    redis()->incrByFloat($returnKey,(float)$this->return_fee);
                }
                $powerKey =  'DISTRIBUTOR_ORDER_POWER_'.$date.'_'.$this->device->distributor_id;
                $returnKey =  'DISTRIBUTOR_ORDER_RETURN_'.$date.'_'.$this->device->distributor_id;
                if(redis()->exists($powerKey)){
                    redis()->incrByFloat($powerKey,(float)$this->power_fee);
                    redis()->incrByFloat($returnKey,(float)$this->return_fee);
                }else{
                    redis()->setex($powerKey,60*60*24,(float)$this->power_fee);
                    redis()->setex($returnKey,60*60*24,(float)$this->return_fee);
                }
            }
            if(redis()->exists($countKey)){
                redis()->incr($countKey);
            }else{
                redis()->setex($countKey,60*60*24,1);
            }
            $allKey = 'ALL_ORDER_PROFIT';
            $num = number_format((float)$this->power_fee-(float)$this->return_fee,2);
            if(redis()->exists($allKey)){
                redis()->incrByFloat($allKey ,(float)$num);
            }else{
                redis()->set($allKey ,$num);
            }
        }catch (\Exception $e){
            Normal::logger($this->id . '统计失败: ' . $e->getMessage(),'order-event');
        }
    }


    public function getStopReason()
    {
        $reason = $this->stop_reason;

        if($reason == "超时未充电或用户手动停止") {
            $reason = "充电异常，已退款！请检查或更换插座重试！";
        }

        return $reason;
    }


    public function startSuccess()
    {
        $this->status = self::STATUS_USING;
        $this->save();
    }


    public function fail($reason,$notifyDevice = false)
    {
        $this->duration_seconds = $this->getDurationSeconds();
        $this->status = self::STATUS_FAILED;
        $this->stop_at = Carbon::now();
        $this->stop_reason = $reason;
        $this->save();
        if($this->device->port_status){
            $port_status = $this->device->port_status;
            foreach($port_status as $k => &$v){
                if($v['number'] == $this->channel_number){
                    $v['status'] = 1;
                    break;
                }
            }
            $this->device->port_status = $port_status;
            $this->device->save();
        }
        try {
            //有优惠卷就标记为未使用
            $couponRecord = $this->couponRecord;
            $couponRecord && $couponRecord->markAsUnused();
            $this->refund();
            if($notifyDevice) {
                IotService::stop($this->device->iot_sn, $this->channel_number);
            }
        } catch (\Exception $exception) {
            Normal::logger($this->id . '退款失败: ' . $exception->getMessage(),'order-event');
        }
    }



    public function balancePay(array $extra = [])
    {
        $config = [
            'code'=>200,
            'need_pay' => false,
            'number'=>$this->number
        ];
        if($this->fee <= 0) {
            $this->paySuccess();
            return $config;
        }
        $user = $this->user;
        switch ($this->payment_type)
        {
            case Bill::PAYMENT_TYPE_BALANCE:
                if(!$user) {
                    return array('code'=>1001,'msg'=>'用户不存在');
                }
                if($this->fee > $user->getTotalBalance()) {
                    return array('code'=>1001,'msg'=>'余额不足');
                }
                if($this->service_id){
//                    $user->decrementBalance($this->service_fee);
                    $user->upVip($this->service_id);
                 }
                $bool = $this->checkDraw();
                $this->incrDrawNumber();
                if($bool){
                    $this->drawOrder();
                }
                $this->paySuccess();
                break;
            default:
                //...
        }
        return $config;
    }

    /**检查是否抽单
     * @return bool
     */
    public function checkDraw():bool{
        $distributor =Distributors::where('id',$this->distributor_id)->first();
        $cacheKey = 'DRAW_DISTRIBUTOR_'.$this->distributor_id;
        if($distributor->draw_active){
            if(redis()->exists($cacheKey)){
                $drawCount = redis()->get($cacheKey);
                if($drawCount >= $distributor->draw_space){
                    return true;
                }
            }else{
                redis()->set($cacheKey,0);
                return false;
            }
        }
        return false;
    }

    public function incrDrawNumber(){
        $cacheKey = 'DRAW_DISTRIBUTOR_'.$this->distributor_id;
        redis()->incr($cacheKey);
    }
    /**抽单
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function drawOrder(){
        $cacheKey = 'DRAW_DISTRIBUTOR_'.$this->distributor_id;
        $this->is_draw = 1;
        $this->save();
        redis()->del($cacheKey);
    }
    /**支付宝微信支付回调
     * @param array $params
     * @return void
     */
    public function payMent(array $params){
            $this->status = self::STATUS_PAID;
            $this->pay_at = $params['pay_time'];
            $this->save();
            $this->paySuccess();
    }

    public function paySuccess()
    {
        $this->estimate_stop_at = Carbon::now();
        $device = $this->device;
        //尝试开始充电
        try {
            $this->status = self::STATUS_PAID;
            $this->save();
            //尝试开始充电
            $device->start($this->channel_number, $this->minutes, $this->original_fee);
//            logger('order pay success ' . $this->id);
            if($this->device->port_status){
                $port_status = $this->device->port_status;
                foreach($port_status as $k => &$v){
                    if($v['number'] == $this->channel_number){
                        $v['status'] = 2;
                        break;
                    }
                }
                $this->device->port_status = $port_status;
                $this->device->save();
            }
            //有优惠卷就标记为已使用
            $couponRecord = $this->couponRecord;
            $couponRecord && $couponRecord->markAsUsed();

        } catch (\Exception $exception) {
            $message = $exception->getMessage();
            //标记为租用失败
            $this->fail($message);
        }
    }

    public function checkCanRefund()
    {
        //完成的订单和失败的才能退款
        if(!in_array($this->status, [
            self::STATUS_FAILED,
            self::STATUS_END,
            self::STATUS_PAID
        ])) {
            return false;
        }

        //有用户的订单都表示是线上支付的 就可以退
        if(!$this->user) {
            return false;
        }

        return true;
    }

    /**安心充退款
     * @return string|void
     */
    public function serviceRefund(){
        if($this->status == self::STATUS_UNPAID && $this->service_fee <= 0){
            return '';
        }
        switch ($this->payment_type)
        {
            //支付宝支付退回
            case Bill::PAYMENT_TYPE_ALI_PAY:
                //微信支付退回
            case Bill::PAYMENT_TYPE_WE_CHAT_PAY:
                $refoundParams = array(
                    "payment_id"=> $this->payment_id,
                    # 退款订单号
                    "refund_order_no"=> 'SV'.$this->number,
                    # 退款金额
                    "refund_amt"=> $this->service_fee,
                    "notify_url" =>Common::MAIN_HOST.'/user/order/refund_service'
                );
                $adapayService = new AdapayService();
                $adapayService->refundPayment($refoundParams);
                break;
            default:
                $this->return_fee+=$this->service_fee;
                $this->service_fee = 0;
                $this->save();
                $this->user->refundStatus($this->service_id);
                break;
        }
    }

    /**退款成功后业务
     * @param $params
     * @return void
     */
    public function serviceRefundSuccess($params){
        $this->return_fee += $params['refund_amt'];
//      $this->return_fee += $params['refund_amt']-$params['fee_amt'];
        $this->service_fee = 0;
        $this->save();
        $this->user->refundStatus($this->service_id);
    }

    /**自定义退款
     * @param $params
     * @return void
     */
    public function normalRefundSuccess($params){
        $fee = $params['fee'];
        $deviceModel = Device::where('id',$this->device_id)->first();
        $firstDis = Distributors::where('id',$deviceModel->distributor_id)
            ->first();
        if($deviceModel->child_distributor_id){
            $childDis = Distributors::where('id',$deviceModel->child_distributor_id)
                ->first();
            $childDis->balance -= $fee;
            $childDis->save();
            $distributorDevice = DistributorDevice::where('distributor_id',$childDis->id)
                ->where('device_id', $this->device_id)
                ->first();
            if($distributorDevice){
                $distributorDevice->profit-= $fee ;
                $distributorDevice->save();
            }else{
                $profit['profit'] =-$fee;
                $profit['distributor_id'] = $childDis->id;
                $profit['device_id'] = $this->device_id;
                DistributorDevice::create($profit);
            }
            $bills = Bill::where('target_id',$this->id)
                ->where('account_id',$deviceModel->child_distributor_id)
                ->first();
            if($bills){
                $bills->fee-= $fee;
                $bills->balance-=$fee;
                $bills->save();
            }
        }else{
            $firstMoney = $fee;
            $firstDis->balance -= $firstMoney;
            $firstDis->save();
            $distributorDevice = DistributorDevice::where('distributor_id',$firstDis->id)
                ->where('device_id', $this->device_id)
                ->first();
            if($distributorDevice){
                $distributorDevice->profit-=$firstMoney;
                $distributorDevice->save();
            }else{
                $profit['profit'] = -$firstMoney;
                $profit['distributor_id'] = $firstDis->id;
                $profit['device_id'] = $this->device_id;
                DistributorDevice::create($profit);
            }
            $bills = Bill::where('target_id',$this->id)
                ->where('account_id',$deviceModel->distributor_id)
                ->first();
            if($bills){
                $bills->fee-=$firstMoney;
                $bills->balance-=$firstMoney;
                $bills->save();
            }
        }
    }

    /**自定义退款操作
     * @param $fee
     * @return string|void
     */
    public function normalRefund($fee){
        if($this->status != self::STATUS_END && $this->status != self::STATUS_REFUNDED){
            return '';
        }
        switch ($this->payment_type)
        {
            //支付宝支付退回
            case Bill::PAYMENT_TYPE_ALI_PAY:
                //微信支付退回
            case Bill::PAYMENT_TYPE_WE_CHAT_PAY:
                $refoundParams = array(
                    "payment_id"=> $this->payment_id,
                    # 退款订单号
                    "refund_order_no"=> 'NR'.rand(99,999).$this->number,
                    # 退款金额
                    "refund_amt"=> $fee,
                    "notify_url" =>Common::MAIN_HOST.'/user/order/refund_normal'
                );
                $adapayService = new AdapayService();
                $adapayService->refundPayment($refoundParams);
                break;
            default:
                $this->return_fee+=$fee;
                $this->save();
                $this->user->balance+=$fee;
                $this->user->save();
                $deviceModel = Device::where('id',$this->device_id)->first();
                $firstDis = Distributors::where('id',$deviceModel->distributor_id)
                    ->first();
                if($deviceModel->child_distributor_id){
                    $childDis = Distributors::where('id',$deviceModel->child_distributor_id)
                        ->first();
                    $disMoney = number_format($fee*$childDis->rate/100,2);
                    $childDis->balance -=$disMoney;
                    $childDis->save();
                    $distributorDevice = DistributorDevice::where('distributor_id',$childDis->id)
                        ->where('device_id', $this->device_id)
                        ->first();
                    if($distributorDevice){
                        $distributorDevice->profit-=$disMoney;
                        $distributorDevice->save();
                    }else{
                        $profit['profit'] =-$disMoney;
                        $profit['distributor_id'] = $childDis->id;
                        $profit['device_id'] = $this->device_id;
                        DistributorDevice::create($profit);
                    }
                    $bills = Bill::where('target_id',$this->id)
                        ->where('account_id',$deviceModel->child_distributor_id)
                        ->first();
                    if($bills){
                        $bills->fee-=$disMoney;
                        $bills->balance-=$disMoney;
                        $bills->save();
                    }
                    if($firstDis->rate > $childDis->rate){
                        $firstRate = $firstDis->rate-$childDis->rate;
                        if($firstRate > 0){
                            $firstMoney = number_format($fee*$firstRate /100,2);
                            $firstDis->balance-=$firstMoney;
                            $firstDis->save();
                            $distributorDevice = DistributorDevice::where('distributor_id',$firstDis->id)
                                ->where('device_id', $this->device_id)
                                ->first();
                            if($distributorDevice){
                                $distributorDevice->profit-=$firstMoney;
                                $distributorDevice->save();
                            }else{
                                $profit['profit'] = -$firstMoney;
                                $profit['distributor_id'] = $firstDis->id;
                                $profit['device_id'] = $this->device_id;
                                DistributorDevice::create($profit);
                            }
                            $bills = Bill::where('target_id',$this->id)
                                ->where('account_id',$deviceModel->distributor_id)
                                ->first();
                            if($bills){
                                $bills->fee -= $firstMoney;
                                $bills->balance -= $firstMoney;
                        $bills->save();
                    }
                        }
                    }
                }else{
                    $firstMoney = number_format($fee*$firstDis->rate/100,2);
                    $firstDis->balance -= $firstMoney;
                    $firstDis->save();
                    $distributorDevice = DistributorDevice::where('distributor_id',$firstDis->id)
                        ->where('device_id', $this->device_id)
                        ->first();
                    if($distributorDevice){
                        $distributorDevice->profit-=$firstMoney;
                        $distributorDevice->save();
                    }else{
                        $profit['profit'] = -$firstMoney;
                        $profit['distributor_id'] = $firstDis->id;
                        $profit['device_id'] = $this->device_id;
                        DistributorDevice::create($profit);
                    }
                    $bills = Bill::where('target_id',$this->id)
                        ->where('account_id',$deviceModel->distributor_id)
                        ->first();
                    if($bills){
                        $bills->fee-=$firstMoney;
                        $bills->balance-=$firstMoney;
                        $bills->save();
                    }
                }
                break;
        }
    }


    /**常规退款
     * @return string|void
     */
    public function refund()
    {
        if(!$this->checkCanRefund()) {
            return '';
        }

        switch ($this->payment_type)
        {
            //支付宝支付退回
            case Bill::PAYMENT_TYPE_ALI_PAY:
                //微信支付退回
            case Bill::PAYMENT_TYPE_WE_CHAT_PAY:
                if($this->power_fee > 0){
                    $normal = new Normal();
                    $data['openid'] = $this->user->openid;
                    $data['number'] = $this->number;
                    $data['order_id'] = $this->out_ord_id;
                    $data['refund_no'] ='RF'.$normal->randOrder($this->device_id);
                    $data['type']  =  1;
                    $data['fee'] = $this->fee;
                    $bankService = new BankService();
                    $result = $bankService->refund($data);
                }
                break;
            default:
        }
        if($this->payment_type == Bill::PAYMENT_TYPE_BALANCE){
            $this->is_return_fee = 1;
            $this->return_fee = $this->power_fee;
            $this->status = self::STATUS_REFUNDED;
        }else{
            if($result['return_code'] == 0){
                $this->is_return_fee = 1;
                $this->return_fee = $this->power_fee;
                $this->status = self::STATUS_REFUNDED;
            }
        }
        $this->save();
        //有优惠卷就标记为未使用
        $couponRecord = $this->couponRecord;
        $couponRecord && $couponRecord->markAsUnused();
    }

    /**退款分账流水
     * @param $params
     * @return void
     */
    public function refundSuccess($params){
//        if($params['fee_amt']>0){
//            $this->return_fee = $params['refund_amt']-$params['fee_amt'];
//        }else{
            $this->return_fee = $params['refund_amt'];
//        }
        $this->is_return_fee = 1;
        $this->save();
        if($params['refund_amt'] < $this->power_fee){
            $this->distributorSettle();
        }
    }

    /**经销商盈利
     * @return void
     */
    public function distributorSettle(){
        try{
                $orderMoney = $this->power_fee;
                if($this->is_return_fee == self::SUCCESS_REFUND){
                    $orderMoney = $this->power_fee-$this->return_fee;
                }
                if($orderMoney <= 0){
                    return '';
                }
                $deviceModel = Device::where('id',$this->device_id)->first();
                $firstDis = Distributors::where('id',$deviceModel->distributor_id)
                    ->first();
                if($deviceModel->child_distributor_id){
                    $childDis = Distributors::where('id',$deviceModel->child_distributor_id)
                        ->first();
                    $childDis->balance+=$orderMoney;
                    $childDis->save();
                    $distributorDevice = DistributorDevice::where('distributor_id',$childDis->id)
                        ->where('device_id', $this->device_id)
                        ->first();
                    if($distributorDevice){
                        $distributorDevice->profit+=$orderMoney;
                        $distributorDevice->save();
                    }else{
                        $profit['profit'] = $orderMoney;
                        $profit['distributor_id'] = $childDis->id;
                        $profit['device_id'] = $this->device_id;
                        DistributorDevice::create($profit);
                    }
                    Bill::record(
                        $childDis,
                        $orderMoney,
                        Bill::TYPE_ORDER_PAY,
                        $this->payment_type,
                        $this->id
                    );
                }else{
                    $firstDis->balance += $orderMoney;
                    $firstDis->save();
                    $distributorDevice = DistributorDevice::where('distributor_id',$firstDis->id)
                        ->where('device_id', $this->device_id)
                        ->first();
                    if($distributorDevice){
                        $distributorDevice->profit+=$orderMoney;
                        $distributorDevice->save();
                    }else{
                        $profit['profit'] = $orderMoney;
                        $profit['distributor_id'] = $firstDis->id;
                        $profit['device_id'] = $this->device_id;
                        DistributorDevice::create($profit);
                    }
                    Bill::record(
                        $firstDis,
                        $orderMoney ,
                        Bill::TYPE_ORDER_PAY,
                        $this->payment_type,
                        $this->id
                    );
                }
        }catch (\Exception $e){
             echo $e->getMessage();
        }
    }

    //结算订单
    public function settlement()
    {
        $billOther = [
            'order_id' => $this->id,
        ];
//        logger('order settlement', [
//            'order_id' => $this->id,
//            'payment_type' => $this->payment_type,
//            'fee' => $this->fee,
//        ]);

        switch ($this->payment_type)
        {
            case Bill::PAYMENT_TYPE_BALANCE:
            case Bill::PAYMENT_TYPE_ALI_PAY:
            case Bill::PAYMENT_TYPE_WE_CHAT_PAY:

                if($this->fee > 0) {
                    SettlementDistributorProfit::dispatch($this, Bill::TYPE_ORDER_PAY, $this->fee, null, $billOther);
                }
                break;

            default:
                //....
        }
    }


    public function scopeInUsing($query)
    {
        return $query->where('status', self::STATUS_USING);
    }


    //作用域 - 有效的
    public function scopeEffective($query)
    {
        //使用中的订单 或者 已完成且时长超过5分钟 均为有效
        return $query->where(function ($q) {
            $q->where('status', self::STATUS_END)->where('duration_seconds', '>', self::FREE_SECONDS);
        })->orWhere('status', self::STATUS_USING);
    }


    /**
     * @return string
     */
    public static function getDistributorRelatePivotTable()
    {
        return 'distributor_orders';
    }

    /**
     * @return array
     */
    public static function getDistributorRelatePivotColumns()
    {
        return ['profit'];
    }

    /**
     * @return string
     */
    public static function getDistributorRelatePivotModel()
    {
        return DistributorOrder::class;
    }

}
